home *** CD-ROM | disk | FTP | other *** search
/ GFX Sensations 1 / Graphic Sensations - Volume 1.iso / tools / amiga / 3d_tools / irit40s.lha / Irit / prsr_lib / soc_srvr.c < prev   
Encoding:
C/C++ Source or Header  |  1994-01-01  |  10.3 KB  |  395 lines

  1. /*****************************************************************************
  2. *   Sockets routines to handle socket io of an objects.                 *
  3. *                                         *
  4. * Written by:  Gershon Elber                Ver 0.1, June 1993.  *
  5. *****************************************************************************/
  6.  
  7. #include <stdio.h>
  8. #include <sys/types.h>
  9.  
  10. #ifdef __UNIX__
  11. #include <signal.h>
  12. #include <sys/socket.h>
  13. #include <netinet/in.h>
  14. #include <netdb.h>
  15. #endif /* __UNIX__ */
  16.  
  17. #ifdef __WINNT__
  18. #include <stdlib.h>
  19. #include <windows.h>
  20. #include <winsock.h>
  21. #include <io.h>
  22. #endif /* __WINNT__ */
  23.  
  24. #include "irit_sm.h"
  25. #include "irit_soc.h"
  26.  
  27. #ifdef OS2GCC
  28. #define INCL_DOSPROCESS
  29. #include <os2.h>
  30.  
  31. static HPIPE
  32.     pipIrit = 0;
  33. #endif /* OS2GCC */
  34.  
  35. static int
  36.     GlblBinaryIPC = FALSE,
  37.     GlblMasterSoc = 0,
  38.     GlblCommuSoc = 0;
  39.  
  40. static void SocketPrintError(char *Str);
  41. #ifdef __UNIX__
  42. #if defined(_AIX) || defined(__hpux)
  43. typedef void (*SignalFuncType)(int); 
  44. #else
  45. typedef void (*SignalFuncType)(void); 
  46. #endif /* _AIX || __hpux */
  47. static void SocNoConnectionHandler(void);
  48. static void SocNoConnectionDummyHandler(void);
  49. #endif /* __UNIX__ */
  50.  
  51. /*****************************************************************************
  52. *  IO error print routine.                             *
  53. *****************************************************************************/
  54. static void SocketPrintError(char *Str)
  55. {
  56. #   if defined(__UNIX__) || defined(OS2GCC)
  57.     perror(Str);
  58. #   endif /* __UNIX__ || OS2GCC */
  59. #   ifdef __WINNT__
  60.     fprintf(stderr, "iritserver: %s error %d\n", Str, WSAGetLastError());
  61. #   endif /* __WINNT__ */
  62. }
  63.  
  64. /*****************************************************************************
  65. *  Write a single char.                                 *
  66. *****************************************************************************/
  67. void SocServerWriteChar(char c)
  68. {
  69. #if defined(__UNIX__) || defined(__WINNT__)
  70.     int i;
  71.  
  72.     if (GlblCommuSoc <= 0) {
  73.     IritPrsrFatalError("Attempt to write to a closed (broken!?) socket");
  74.     return;
  75.     }
  76.  
  77.     while ((i = send(GlblCommuSoc, &c, 1, 0)) != 1) {
  78.     if (i < 0)                   /* Lost connection probably. */
  79.         SocServerCloseSocket();
  80.     IritSleep(10);
  81.     }
  82. #endif /* __UNIX__ || __WINNT__ */
  83. #ifdef OS2GCC
  84.     ULONG BytesWritten;
  85.     ULONG rc;
  86.  
  87.     rc = DosWrite(pipIrit, &c, 1, &BytesWritten);
  88. #endif /* OS2GCC */
  89. }
  90.  
  91. /*****************************************************************************
  92. *  Write a single line of line length characters.                 *
  93. *****************************************************************************/
  94. void SocServerWriteLine(char *Line, int LineLen)
  95. {
  96. #if defined(__UNIX__) || defined(__WINNT__)
  97.     int i;
  98.  
  99.     if (GlblCommuSoc <= 0) {
  100.     IritPrsrFatalError("Attempt to write to a closed (broken!?) socket");
  101.     return;
  102.     }
  103.  
  104.     while ((i = send(GlblCommuSoc, Line, LineLen, 0)) < LineLen) {
  105.     if (i < 0)                   /* Lost connection probably. */
  106.         SocServerCloseSocket();
  107.     IritSleep(10);
  108.     LineLen = LineLen - i;
  109.     Line = &Line[i];
  110.     }
  111. #endif /* __UNIX__ || __WINNT__ */
  112. #ifdef OS2GCC
  113.     ULONG BytesWritten;
  114.     ULONG rc;
  115.  
  116.     rc = DosWrite(pipIrit, Line, LineLen, &BytesWritten);
  117. #endif /* OS2GCC */
  118. }
  119.  
  120. /*****************************************************************************
  121. *  Creates a server socket. Returns TRUE if successful.                 *
  122. *****************************************************************************/
  123. int SocServerCreateSocket(void)
  124. {
  125. #if defined(__UNIX__) || defined(__WINNT__)
  126.     int s;
  127.     char *portnum;
  128.     struct sockaddr_in sain;
  129.     struct servent *serv;
  130.  
  131.     ZAP_MEM(&sain, sizeof(struct sockaddr_in));
  132.     sain.sin_addr.s_addr = htonl(INADDR_ANY);
  133.     sain.sin_family = AF_INET;
  134.  
  135. #ifdef __WINNT__
  136.     {
  137.     WSADATA WSAData;
  138.  
  139.     if ((s = WSAStartup(MAKEWORD(1, 1), &WSAData)) != 0) {
  140.          fprintf(stderr, "iritserver: WSAStartup: error %d\n",
  141.              WSAGetLastError());
  142.          exit(1);
  143.     }
  144.     }
  145. #endif
  146.  
  147.     if ((portnum = getenv("IRIT_SERVER_PORT")) != NULL)
  148.     sain.sin_port = atoi(portnum);
  149.     else if ((serv = getservbyname(IRIT_TCP_SERVICE, "tcp")) == NULL)
  150.     sain.sin_port = htons(IRIT_TCP_PORT);
  151.     else
  152.     sain.sin_port = serv->s_port;
  153.  
  154.     /* Create the socket and bind. */
  155.     if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  156.     IritPrsrFatalError("iritserver: socket");
  157.     return FALSE;
  158.     }
  159.     if (bind(s, (struct sockaddr *) &sain, sizeof(struct sockaddr_in)) < 0) {
  160.     IritPrsrFatalError("iritserver: bind");
  161.     return FALSE;
  162.     }
  163.  
  164.     if (listen(s, 5) < 0) {
  165.     IritPrsrFatalError("iritserver: listen");
  166.     return FALSE;
  167.     }
  168.  
  169. #ifdef __UNIX__
  170.     signal(SIGPIPE, (SignalFuncType) SocNoConnectionHandler);
  171. #endif /* __UNIX__ */
  172.  
  173.     GlblMasterSoc = s;
  174.  
  175. #endif /* __UNIX__ || __WINNT__ */
  176.  
  177.     GlblBinaryIPC = getenv("IRIT_BIN_IPC") != NULL;
  178.  
  179.     return TRUE;
  180. }
  181.  
  182. /*****************************************************************************
  183. *  Accept a client socket connection. Blocks until connection is established.*
  184. *****************************************************************************/
  185. void SocServerAcceptConnection(void)
  186. {
  187. #if defined(__UNIX__) || defined(__WINNT__)
  188.     struct sockaddr_in client_sain;
  189.     int len = sizeof(client_sain);
  190.  
  191.     while ((GlblCommuSoc = accept(GlblMasterSoc,
  192.                   (struct sockaddr *) &client_sain,
  193.                   &len)) < 0);
  194. #endif /* __UNIX__ || __WINNT__ */
  195. #ifdef OS2GCC
  196.     ULONG rc;
  197.     rc = DosCreateNPipe(IRIT_PIPE,        /* Drawing command pipe. */
  198.             &pipIrit,
  199.             NP_ACCESS_DUPLEX | NP_NOWRITEBEHIND,
  200.             NP_WAIT | NP_TYPE_BYTE | NP_READMODE_BYTE | 1,
  201.             IRIT_PIPE_BUFFER_SIZE,
  202.             IRIT_PIPE_BUFFER_SIZE,
  203.             0);
  204.  
  205.     if (rc != 0) {
  206.     fprintf(stderr,
  207.         "DosCreateNPipe: error in creating %s\n", IRIT_PIPE);
  208.     exit(1);
  209.     }
  210.  
  211.     if ((rc = DosConnectNPipe(pipIrit)) != 0) {
  212.     fprintf(stderr,
  213.         "DosConnectNPipe: error in connection %s\n",
  214.         IRIT_PIPE);
  215.     exit(1);
  216.     }
  217.  
  218.     GlblCommuSoc = (int) pipIrit;
  219. #endif /* OS2GCC */
  220. }
  221.  
  222. /*****************************************************************************
  223. *  Close a server socket.                             *
  224. *****************************************************************************/
  225. void SocServerCloseSocket(void)
  226. {
  227.     if (GlblCommuSoc > 0) {
  228. #ifdef __UNIX__
  229.     char Line[LINE_LEN];
  230.  
  231.     /* Force the system to realize that the connection is down. This is */
  232.     /* a kluge to solve the time out problem that happens under unix.   */
  233.     IritSleep(1000);
  234.     signal(SIGPIPE, (SignalFuncType) SocNoConnectionDummyHandler);
  235.     send(GlblCommuSoc, Line, LINE_LEN, 0);
  236.  
  237.     if (close(GlblCommuSoc) != 0)
  238.         SocketPrintError("iritserver: close");
  239. #endif /* __UNIX__ */
  240. #ifdef __WINNT__
  241.     closesocket(GlblCommuSoc);
  242. #endif /* __WINNT__ */
  243.  
  244.     GlblCommuSoc = 0;
  245.     }
  246. }
  247.  
  248. /*****************************************************************************
  249. *  Returns TRUE if connection is active.                     *
  250. *****************************************************************************/
  251. int SocServerActive(void)
  252. {
  253.     return GlblCommuSoc > 0;
  254. }
  255.  
  256. #ifdef __UNIX__
  257. /*****************************************************************************
  258. *  Clean the server socket in case of a broken pipe.                 *
  259. *****************************************************************************/
  260. static void SocNoConnectionHandler(void)
  261. {
  262.     SocServerCloseSocket();
  263.     signal(SIGPIPE, (SignalFuncType) SocNoConnectionHandler);
  264.     IritPrsrParserAbort(IP_ERR_SOCKET_BROKEN, "");
  265. }
  266. /*****************************************************************************
  267. *  Dummy handler                                 *
  268. *****************************************************************************/
  269. static void SocNoConnectionDummyHandler(void)
  270. {
  271. }
  272. #endif /* __UNIX__ */
  273.  
  274. /*****************************************************************************
  275. * Attempt to write an object to a socket.                     *
  276. *****************************************************************************/
  277. void SocServerWriteOneObject(IPObjectStruct *PObj)
  278. {
  279.     char *ErrorMsg;
  280.  
  281.     if (GlblCommuSoc <= 0) {
  282.     char *DisplayStr;
  283.  
  284.     /* Needs to start up the client display - it is not up yet */
  285.     if ((DisplayStr = getenv("IRIT_DISPLAY")) != NULL) {
  286. #ifdef OS2GCC
  287.         char LoadError[LINE_LEN], Env[LINE_LEN];
  288.         RESULTCODES Results;
  289.         ULONG rc;
  290.         int i;
  291.  
  292.         strcpy(Env, "IRIT_DISPLAY_S=1");
  293.         i = strlen(Env) + 1;
  294.         if (GlblBinaryIPC) {
  295.             strcpy(&Env[i], "IRIT_BIN_IPC=1");
  296.         i += strlen(&Env[i]) + 1;
  297.         }
  298.         Env[i] = '\0';
  299.  
  300.         LoadError[0] = 0;
  301.         rc = DosExecPgm(LoadError,
  302.                 sizeof(LoadError),
  303.                 EXEC_BACKGROUND,
  304.                 "",
  305.                 Env,
  306.                 &Results,
  307.                 DisplayStr);
  308.         if (rc != 0) {
  309.         fprintf(stderr,
  310.             "DosExecPgm: (Error %d) \"%s\"\n", rc, LoadError);
  311.         exit(1);
  312.         }
  313. #else
  314. #ifdef __UNIX__
  315.         char DisplayCommand[LINE_LEN];
  316.  
  317.         sprintf(DisplayCommand, "%s &", DisplayStr);
  318.         system(DisplayCommand);
  319. #else
  320. #ifdef __WINNT__
  321.         char DisplayCommand[LINE_LEN];
  322.  
  323.         sprintf(DisplayCommand, "start %s", DisplayStr);
  324.         system(DisplayCommand);
  325. #else
  326. #endif /* __WINNT__ */
  327. #endif /* __UNIX__ */
  328. #endif /* OS2GCC */
  329.     }
  330.     else
  331.         fprintf(stderr,
  332.             "Irit: Startup your display device - I am waiting...\n");
  333.     SocServerAcceptConnection();
  334.     fprintf(stderr, "Irit: Connection with client established.\n");
  335.  
  336. #ifdef __UNIX__
  337.     signal(SIGPIPE, (SignalFuncType) SocNoConnectionHandler);
  338. #endif /* __UNIX__ */
  339.     }
  340.  
  341.     if (IP_IS_UNDEF_OBJ(PObj)) {
  342.     fprintf(stderr, "Socket: Attempt to write an undefined object.\n");
  343.     return;
  344.     }
  345.  
  346.     IritPrsrWriteSocket(TRUE);
  347.     if (GlblBinaryIPC) {
  348.     IritPrsrPutBinObject(NULL, PObj);
  349.     }
  350.     else {
  351.     IritPrsrPutObject(NULL, PObj);
  352.     }
  353.     IritPrsrWriteSocket(FALSE);
  354.  
  355.     if (IritPrsrParseError(&ErrorMsg)) {
  356.     fprintf(stderr, "Socket: %s\n", ErrorMsg);
  357.     }
  358. }
  359.  
  360. #ifdef DEBUG_SERVER
  361.  
  362. /*****************************************************************************
  363. * Simple test for the server - reads file and dumps one object every key.    *
  364. *****************************************************************************/
  365. void main(int argc, char ** argv)
  366. {
  367.     FILE
  368.     *f = argc == 2 ? fopen(argv[1], "r") : stdin;
  369.     IPObjectStruct *PObj,
  370.         *PObjClear = IPAllocObject("_COMMAND_", IP_OBJ_STRING, NULL),
  371.     *PObjs = IritPrsrGetObjects(f);
  372.  
  373.     if (argc == 2)
  374.     fclose(f);
  375.     strcpy(PObjClear -> U.Str, "CLEAR");
  376.  
  377.     SocServerCreateSocket();
  378.  
  379.     while (TRUE) {
  380.     for (PObj = PObjs; PObj != NULL; PObj = PObj -> Pnext) {
  381.         fprintf(stderr, "Press return to send data.\n");
  382.         getchar();
  383.         SocServerWriteOneObject(PObj);
  384.     }
  385.  
  386.     fprintf(stderr, "Done. Press return to send clear.\n");
  387.     getchar();
  388.     SocServerWriteOneObject(PObjClear);
  389.     }
  390.  
  391.     SocServerCloseSocket();
  392. }
  393.  
  394. #endif /* DEBUG_SERVER */
  395.